#include <iostream>
#include <string>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Common.hpp"
#include "Log.hpp"
#include "Protocol.hpp"
using namespace LogModule;
int main(int args, char *argv[])
{
    if (args != 3)
    {
        LOG(Loglevel::FATAL) << "Usage :serverip serverport";
        Die(USAGE_ERR);
    }
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        LOG(Loglevel::FATAL) << "socket filed";
        Die(SOCKET_ERR);
    }
    LOG(Loglevel::INFO) << "socket success,sockfd:" << sockfd;
    // 填充网络信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    server.sin_addr.s_addr = inet_addr(server_ip.c_str());
    // 不需要显式进行bind绑定
    // TCP建立在连接之上
    int n = connect(sockfd, CONV(&server), sizeof(server));
    if (n < 0)
    {
        LOG(Loglevel::ERROR) << "connect filed";
    }
    LOG(Loglevel::INFO) << "connect success,sockfd:" << sockfd;

    // 进行网络通信
    std::string message;
    while (true)
    {
        int x, y;
        char oper;
        std::cout << "input x#";
        std::cin >> x;
        std::cout << "input y#";
        std::cin >> y;
        std::cout << "input oper#";
        std::cin >> oper;
        Request req(x, y, oper);
        // 序列化
        req.Serizlize(message);
        // 添加报头
        Encode(message);
        n = send(sockfd, message.c_str(), message.size(), 0); // 使用message.size()而非sizeof(message)
        if (n > 0)
        {
            char inbuffer[4096];
            int m = recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0);
            if (m > 0)
            {
                inbuffer[m] = 0;
                std::string package = inbuffer;
                std::string content;
                // 去掉报头
                Decode(package, &content);

                // std::cout<<content<<std::endl; //Test
                // 反序列化
                Response resp;
                resp.Deserizlize(content);

                // std::cout<<content<<std::endl;   //Test
                // 得到结构化的数据
                std::cout << resp.Result() << "[" << resp.Code() << "]" << std::endl;
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
    close(sockfd);
    return 0;
}